<?php
/**
 * Module: Func
 * 
 * This module provides functions for common tasks such as formatting time or size,
 * stripping format from IRC messages, or even calculating adler32 hashes. If you have 
 * made a function which could be useful for other modules, add it in here as a static
 * method.
 * 
 * Author: MrBondt
 *         mrbondt@goldenak.eu
 */
class Func extends ModuleBase {
	/**
	 * Function: getPieces
	 * Argument: aInput (array) - The input array
	 * Argument: sSep (string) - The string to put between the elements
	 * Argument: iStart (int) - The index of the element of where to start in the array
	 * Argument: iEnd (int) - The index of the element of where to end in the array
	 * 
	 * This static method allows you to extract a certain range of elements out of an
	 * array, and return it as a string. Very similar to PHP's implode() function, only
	 * this method allows you to specify a range in the input array.
	 */
	public static function getPieces ($aInput, $sSep = ' ', $iStart = 0, $iEnd = null) {
		return implode ($sSep, array_slice ($aInput, $iStart, $iEnd));
	}
	
	/**
	 * Function: formatTime
	 * Argument: nSeconds (int) - The number of seconds
	 * Argument: bShort (bool) - Do you want a short notation?
	 * 
	 * Converts the input number of seconds to a human readable string. This can
	 * either be a full featured string or a short one with only the first letters
	 * of the units.
	 */
	public static function formatTime ($nSeconds, $bShort = false) {
		$aModulos = array (31449600, 604800, 86400, 3600, 60, 1);
		
		// It is possible to define your own language.
		if ($bShort) {
			$aLanguage = array
			(
				's' => array ('y', 'w', 'd', 'h', 'm', 's'),
				'p'	=> array ('y', 'w', 'd', 'h', 'm', 's'),
				'and' => '',
			);
		} else {
			$aLanguage = array
			(
				's' => array ('year', 'week', 'day', 'hour', 'minute', 'second'),
				'p'	=> array ('years', 'weeks', 'days', 'hours', 'minutes', 'seconds'),
				'and' => 'and',
			);
		}
		
		// Extract the time units.
		$sTime = '';
		foreach ($aModulos as $i => $nModulo) {
			if ($nSeconds == 0) break;
			
			$nResult = floor ($nSeconds / $nModulo);
			if ($nResult > 0) {
				// Remove the time unit from the total.
				$nSeconds %= $nModulo;
				
				if (strlen ($sTime) != 0) {
					// This is not the first element.
					if ($bShort) {
						$sTime .= ' ';
					} else {
						if (!isset ($aModulos [$i + 1]) || $aModulos [$i + 1] > $nSeconds) {
							// This is the last loop, add 'and'.
							$sTime .= ' ' . $aLanguage ['and'] . ' ';
						} else {
							// More is coming, add a comma.
							$sTime .= ', ';
						}
					}
				}
				
				$sTime .= $nResult;
				if (!$bShort) $sTime .= ' ';
				
				if ($nResult == 1) {
					// Use single.
					$sTime .= $aLanguage ['s'][$i];
				} else {
					// Use plural.
					$sTime .= $aLanguage ['p'][$i];
				}
			}
		}
		
		if (strlen ($sTime) == 0) {
			// Still empty? Make something nice.
			$sTime = '0' . ($bShort ? '' : ' ') . $aLanguage ['p'][count ($aLanguage['p']) - 1];
		}
		
		return $sTime;
	}
	
	/**
	 * Function: formatSize
	 * Argument: nSize (int) - The size to format
	 * Argument: nDecimals (int) - The number of decimals to show
	 * Argument: sCurrentUnit (string) - The symbol of the unit nSize currently is in
	 * 
	 * Formats a given size to a human readable string. It allows you to specify the 
	 * number of decimals, as well as the unit the size currently is in. This is for
	 * optimum performace.
	 */
	public static function formatSize ($nSize, $nDecimals = 2, $sCurrentUnit = null) {
		$aSizes = array ('', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y');
		
		$i = 0;
		if ($sCurrentUnit != null) $i = (int) array_search (strtoupper ($sCurrentUnit [0]), $aSizes);
		
		// Keep dividing while we have units and more than 1024 of them.
		while ($nSize >= 1024 && $i < 8) {
			$i++;
			$nSize /= 1024;
		}
		
		return round ($nSize, $nDecimals) . ' ' . $aSizes [$i] . 'B';
	}
	
	/**
	 * Function: stripFormat
	 * Argument: sMessage (string) - The message to strip the format of
	 * 
	 * This function removes all IRC formatting from the given message.
	 */
	public static function stripFormat ($sMessage) {
		return preg_replace ('/(' . chr(2) . '|' . 
									chr(3) . '\d{1,2}(?:,\d{1,2}|)|' . 
									chr(15) . '|' . 
									chr(22) . '|' . 
									chr(31) . ')/', 
									'', 
									$sMessage);
	}
	
	/**
	 * Function: parseMessage
	 * Argument: sMessage (string) - The message to be parsed
	 * 
	 * This function will split the message into usable pieces for commands,
	 * a trigger, the string with all parameters and all parameters into a
	 * by spaces split array.
	 */
	public static function parseMessage ($sMessage) {
		if (strpos ($sMessage, ' ') !== false) {
			list ($sTrigger, $sParams) = explode (' ', $sMessage, 2);
			$sParams = trim ($sParams);
			$aParams = explode (' ', $sParams);
		} else {
			$sTrigger = $sMessage;
			$sParams = null;
			$aParams = array ();
		}
		
		return array ($sTrigger, $sParams, $aParams);
	}
	
	/**
	 * Function: adler32
	 * Argument: sInput (string) - The input to calculate the hash of
	 * 
	 * This function calculates the adler32 hash of the given string. Very useful
	 * for filenames, as this only outputs a number.
	 */
	public static function adler32 ($sInput) {
		$s1 = 1;
		$s2 = $s4 = 0;
		for($i = 0 ; $i < strlen ($sInput) ; $i++) {
			$s1 = ($s1 + ord ($sInput [$i])) % 65521;
			$s2 = ($s2 + $s1) % 65521;
		}
		$s3 = decbin ($s2);
		for ($i = 0; $i < (64 - strlen ($s3)); $i++) {
			$s3 = "0" . $s3;
		}
		for ($i = 0; $i < 16; $i++) {
			$s3 = substr ($s3 . "0", 1);
		}
		for ($i = 0; $i < strlen ($s3); $i++) {
			$s4 = $s4 + $s3 [$i] * pow (2, strlen ($s3) - $i - 1);
		}
	
		return $s4 + $s1;
	}
}
?>